#include "nim-common.h"

// helper function to perform "safe" tcp transfer
// expects sending/recieving exact length
// retries NUMBER_OF_TRANSFER_TRIES times, and fails afterwards
bool safeTransfer(const int &sock, char *buf, const int length, bool isSend) {
	int total = 0;
	int bytesLeft = length;
	int n;
	int times = NUMBER_OF_TRANSFER_TRIES;
	while(total < length && times) {
		if (isSend) {
			n = send(sock, buf+total, bytesLeft, 0);
		} else {
			n = recv(sock, buf+total, bytesLeft, 0);
		}
		if (n == -1) {
			return false;
		}
		total += n;
		bytesLeft -= n;
		times--;
	}
	return times ? true : false;
}

bool safeSend(const int &sock, char *buf, const int length) {
	return safeTransfer(sock,buf,length,true);
}

bool safeRecv(const int &sock, char *buf, const int length) {
	return safeTransfer(sock,buf,length,false);
}

// return the actual message length excluding the opcode
int getMessageLengthByOpCode(int opCode) {

	int result;

	switch(opCode) {
	case OPCODE_STATUS:
		result = OPCODE_STATUS_LENGTH;
		break;
	case OPCODE_ACK:
		result = OPCODE_ACK_LENGTH;
		break;
	case OPCODE_GAME_TYPE:
		result = OPCODE_GAME_TYPE_LENGTH;
		break;
	case OPCODE_GAME_END_STATUS:
		result = OPCODE_GAME_END_STATUS_LENGTH;
		break;
	case OPCODE_SERVER_MESSAGE:
		result = OPCODE_SERVER_MESSAGE_HEADER_LENGTH;
		break;
	case OPCODE_YOUR_TURN:
		result = OPCODE_YOUR_TURN_LENGTH;
		break;
	case OPCODE_PLAYER_STATUS:
		result = OPCODE_PLAYER_STATUS_LENGTH;
		break;
	case OPCODE_PLAYER_GAME_STATUS:
		result = OPCODE_PLAYER_GAME_STATUS_LENGTH;
		break;
	case OPCODE_ILLEGAL_NOT_IN_TURN_MESSAGE:
		result = OPCODE_ILLEGAL_NOT_IN_TURN_MESSAGE_LENGHT;
		break;
	case OPCODE_CLIENT_REJECTED:
		result = OPCODE_CLIENT_REJECTED_LENGTH;
		break;
	case OPCODE_CLIENT_MOVE:
		result = OPCODE_CLIENT_MOVE_LENGTH;
		break;
	case OPCODE_CLIENT_MESSAGE:
		result = OPCODE_CLIENT_MESSAGE_HEADER_LENGTH;
		break;
	case OPCODE_CLIENT_ILLEGAL_MOVE:
		result = OPCODE_CLIENT_ILLEGAL_MOVE_LENGTH;
		break;
	case OPCODE_CLIENT_QUIT:
		result = OPCODE_CLIENT_QUIT_LENGTH;
		break;
	default:
		result = 0;
		break;
	}

	result -= 1;

	return result;
}
